package com.spark.shiro.interceptor;

import com.spark.shiro.bean.PageBean;
import org.apache.ibatis.executor.parameter.ParameterHandler;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.ReflectorFactory;
import org.apache.ibatis.reflection.SystemMetaObject;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Map;
import java.util.Properties;

/**
 * Created by tyd on 2017-10-30.
 *
 * @author tyd
 */
@Intercepts(@Signature(type = StatementHandler.class, args = {Connection.class}, method = "prepare"))
public class PageInterceptor implements Interceptor {


    private String pageEndStr;

    @Override
    public Object intercept(Invocation invocation) throws Throwable {


        if (invocation.getTarget() instanceof StatementHandler) {

            StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
            MetaObject metaObject = SystemMetaObject.forObject(statementHandler);

            metaObject.getObjectFactory();

            MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement");

            if (mappedStatement.getId().endsWith(pageEndStr)) {

                BoundSql boundSql = statementHandler.getBoundSql();

                //获取总数
                String countSql = "select count(*) as total from (" + boundSql.getSql() + ") a";
                Object[] args = invocation.getArgs();
                Connection conn = (Connection) args[0];

                PreparedStatement pstmt = conn.prepareStatement(countSql);

                //设置查询参数
                ParameterHandler parameterHandler = (ParameterHandler) metaObject.getValue("delegate.parameterHandler");

                parameterHandler.setParameters(pstmt);

                ResultSet rs = pstmt.executeQuery();

                int total = 0;
                if (rs.next()) {
                    total = rs.getInt("total");
                }

                Map<?, ?> map = (Map<?, ?>) boundSql.getParameterObject();

                PageBean pageBean = (PageBean) map.get("pageBean");

                pageBean.setTotal(total);

                String newSql = statementHandler.getBoundSql().getSql() + " limit " + pageBean.getIndex() + "," + pageBean.getPageNum();

                metaObject.setValue("delegate.boundSql.sql", newSql);
            }

        }
        return invocation.proceed();
    }

    @Override
    public Object plugin(Object o) {
        return Plugin.wrap(o, this);
    }

    @Override
    public void setProperties(Properties properties) {
        this.pageEndStr = (String) properties.get("pageEndStr");
    }
}
